home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1997 September
/
Macworld (1997-09).dmg
/
Shareware World
/
Utilities
/
Text Processing
/
Alpha
/
Tcl
/
Modes
/
perl.tcl
< prev
next >
Wrap
Text File
|
1997-04-02
|
50KB
|
1,672 lines
#############################################################################
# MacPerl.tcl
# -----------
#
# This is a set of routines that allow Alpha to act as a front end for the
# standalone MacPerl application and that allow Perl scripts to be used as
# text filters in Alpha. These functions are accessed through a special
# MacPerl menu.
#
# The features of this package are explained in the file "MacPerl Help",
# accessible from the Help menu.
#
#############################################################################
#
# If you don't already have MacPerl, it's available by anonymous ftp from
# the umich site
#
# mac.archive.umich.edu [141.211.165.34] mac/development/languages
#
# and its mirrors. Also, MacPerl's home site is
#
# ftp.switch.ch [130.59.1.40] software/mac/src/mpw_c
#
# MacPerl was written (ported to the Mac) by
# Matthias Neeracher <neeri@iis.ee.ethz.ch> , and
# Tim Endres <time@ice.com>.
#
#############################################################################
# Author: Tom Pollard <pollard@schrodinger.com>
#
# Contributors: Dan Herron <herron@cogsci.ucsd.edu>
# David Schooley <schooley@ee.gatech.edu>
# Vince Darley <vince@das.harvard.edu>
# Martijn Koster <m.koster@nexor.co.uk>
#
# Version History:
#
# 3.0 4/97 - MacPerl interactions don't depend on MacPerl app name anymore
# Fixed bug with perlFileAsFilter ($scriptStart uninitialized)
# 2.9 3/97 - Fixed bug in command-dbl-click help lookup for Perl5 mode
# 2.8 2/97 - Added Quick-Save commands in new submenu [Dan Herron]
# "Save As CGI" finally works.
# 2.7 2/97 - Comments before "#!/bin/perl" no longer confuse 'gotoPerlError'
# 2.6 2/97 - Added electricPerlLeft and electricPerlRight - [David Schooley]
# 2.51 1/96 - Fixed problem w/ "Tell MacPerl:Save As..."
# 2.5 1/96 - Colorization and cmd-dbl-click modified to support Perl 5 docs
# 2.41 7/95 - Minor tweaks
# 2.4 7/95 - Fixed bugs affecting running unsaved scripts and error handling
# 2.3 7/95 - Minor tweaks and code rearrangement.
# 2.2 6/95 - Text filters act only on current line if "Apply to Buffer" is
# false and no text has been selected.
# Bug fix in error-marking for scripts sent as AppleEvent params.
# Cmd-dbl-clicking a function call jumps to function, if
# defined in the same file.
# 2.1 6/95 - Cmd-dbl-clicking a 'require'd filename opens the file.
# 2.0 6/95 - Minor bug fixes (incl. keyword decapitalization)
# Alpha 6.0b17 compatibility updates.
# Text Filters folder is settable from the App Paths menu now.
# 1.9 5/95 - Cmd-dbl-clicking Perl keywords and special variables displays
# the man page info.
# 1.81 4/95 - one very minor Alpha compatibility update (winInfo->getWinInfo).
# 1.8 4/95 - Menu reorganized somewhat.
# Text Filters folder can now be anywhere.
# "ApplyToBuffer" flag ignored if text has been selected.
# Bug fixes.
# 1.7 1/95 - Updated to take advantage of MacPerl 4.1.4 AppleEvent features:
# 1) Text filters use 'batch' doScript (.: STDOUT file obsolete)
# 2) Filter scripts sent as doScript params (.: SCRIPT file obsolete)
# 3) "Save As Droplet" and "Save as Runtime" commands added.
# Errors generated in 'require'd files are now displayed correctly
# 1.6 10/94 - "UseDebugger" flag added (forces scripts to run under debugger).
# Key bindings added for some menu commands.
# "perlDoScript{,2,3}" procs consolidated into a single proc.
# "saveAndRun" option added.
# Command-line args now parsed into units more correctly, in
# particular, quoted file names aren't broken up.
# "Close Output Window" added to "Tell MacPerl" menu.
# Updated for Alpha 5.98 to load when menu is inserted.
# The error messages window is now recycled.
# "perlRecycleOutput" recycles output window.
# Minor bug fixes.
# 1.5 9/94 - MacPerl menu rearranged somewhat.
# Explicit "Get Output Window" command added to menu.
# Reading "#!" line for args is incompatible w/ standard,
# so it's been dropped.
# Only scan the first 40 output lines for error messages (faster)
# "wrapFilterScript" no longer opens STDIN
# Text filters may now use command-line args
# STDIN for text filters passed as explicit cmd-line arg
# 1.4 9/94 - The "#!" line of every script is read for command-line args,
# which are passed explicitly to MacPerl with the script.
# "PromptForArgs" menu flag added.
# "perlCmdlineArgs" modeVar holds default command-line args.
# Scripts are sent using custom "perlDoScript2" proc, which
# allows passing of explicit command-line args.
# 1.3 9/94 - When any script generates a compilation error, the file
# containing the script is brought up with the offending
# line highlighted; all error output is also written to
# a "Perl Error Messages" window.
# 'repeatLastFilter' runs again the last text-filter script used.
# 'perlLastFilter' modeVar holds pathname of last filter.
# Menu flags now mirrored as modeVars, so they can be saved and
# restored between sessions.
# Minor bug fixes.
# 1.2 8/94 - 'retrieveOutput' and 'autoSwitch' flags added.
# 'openInMacperl' added.
# MacPerl output window now closed before new scripts are sent.
# Filters now abort if there are compilation errors, and
# MacPerl diagnostic output retrieved and displayed in Alpha.
# 1.1 8/94 - 'quitMacperl' added.
# perl-mode file-marking updated for Alpha 5.90
# Simplified installation via 'loadMacperl'(Pete Keleher).
# 1.0 7/94 - perl-mode setup updated for Alpha 5.85:
# keyword colorization supported
# custom file-marking added
# #! lines in filter scripts now handled correctly
# Workarounds installed for AppleEvent bug in MacPerl 4.1.3
# 0.9 3/94 - perl-mode stuff added, and
# highlighted 'Perl commands' file (man page) prepared
# minor bug fixes, too
# 0.8 3/94 - flags are now check-marked
# 0.7 3/94 - nested Text Filters folder now supported
# menu format modified somewhat
# 0.6 3/94 - 'applyToBuffer' flag added
# scripts in Alpha buffers can now be used as filters
# 0.5 2/94 - 'filters', 'open special' submenu added
# 'overwrite' flag added
# 0.2 1/94 - menu support added (Martijn Koster <m.koster@nexor.co.uk>)
# 'execute selection', 'execute buffer' commands added
# 0.1 9/93 - text filter functionality created
#
##############################################################################
#
proc dummyPerl {} {
}
#############################################################################
# Default settings for the Perl menu flags
#
set perlDefault(perlUseDebug) 0
set perlDefault(perlGetOutput) 1
set perlDefault(perlAutoSwitch) 1
set perlDefault(perlOverwrite) 0
set perlDefault(perlUsebuffer) 1
set perlDefault(perlPromptArgs) 0
set perlDefault(perlRecycleOutput) 0
set perlDefault(perlPrevScript) {*startup*}
set perlDefault(perlCmdlineArgs) {}
set perlDefault(perlVersion) {4}
if {![info exists perlFilterPath]} {
set perlFilterPath "$HOME:Tcl:UserCode:Text Filters:"
}
foreach var [array names perlDefault] {
if (![info exists PerlmodeVars($var)]) {
set $var $perlDefault($var)
} else {
set $var $PerlmodeVars($var)
}
}
unset perlDefault
##############################################################################
# Make duplicate copies of these variables as modeVars, taking responsibility
# for keeping the two sets consistent (argh!)
#
# (Maybe it's OK now to let them _just_ be modeVars, and not also ordinary
# variables?)
#
newModeVar Perl perlUseDebug $perlUseDebug 1
newModeVar Perl perlGetOutput $perlGetOutput 1
newModeVar Perl perlAutoSwitch $perlAutoSwitch 1
newModeVar Perl perlOverwrite $perlOverwrite 1
newModeVar Perl perlUsebuffer $perlUsebuffer 1
newModeVar Perl perlPromptArgs $perlPromptArgs 1
newModeVar Perl perlRecycleOutput $perlRecycleOutput 1
newModeVar Perl perlLastFilter $perlPrevScript 0
newModeVar Perl perlCmdlineArgs $perlCmdlineArgs 0
##############################################################################
# Other Perl-mode variable definitions
#
newModeVar Perl elecRBrace {0} 1
newModeVar Perl elecLBrace {1} 1
newModeVar Perl electricSemi {0} 1
newModeVar Perl electricTab {1} 1
newModeVar Perl electricReturn {1} 1
newModeVar Perl wordBreak {(\$)?\w+} 0
newModeVar Perl prefixString {# } 0
newModeVar Perl wordWrap {0} 1
newModeVar Perl funcExpr {^sub *([+-a-zA-Z0-9]+)} 0
newModeVar Perl wordBreakPreface {[^a-zA-Z0-9_\$]} 0
newModeVar Perl autoMark 1 1
newModeVar Perl stringColor green 0
newModeVar Perl perlVersion $perlVersion 0
##############################################################################
# Miscellaneous definitions
#
set perlErrorWindow {* Perl Error Messages *}
set perlOutputWindow {* Perl Output *}
set interpPat {(#![ !-~]*)}
set perlFilterMenu "textFilters"
set modeCode ":Tcl:Modes:perl${perlVersion}.tcl"
if {[catch {source $HOME$modeCode}]} {
alertnote "Couldn't load the Perl-mode colorization file \"$modeCode\". Contact the maintainer."
}
#############################################################################
# Return paths to standard files, based on the path to MacPerl:
#
proc macperlFolder {} {
set name [nameFromAppl McPL]
regexp {(.*):([^:]*)} $name pathname dirname filename
return ${dirname}:
}
proc stdinPath {} {
return [macperlFolder]STDIN
}
proc scriptPath {} {
return [macperlFolder]SCRIPT
}
#############################################################################
# Define the dummy proc that will be called when the perl menu
# is first inserted into the menubar
#
proc perlMenu {} {}
#############################################################################
# Build the perl menu
#
set perlMenu "•132"
set perlOptsMenu "generalOptions"
set filtOptsMenu "filterOptions"
menu -n $perlMenu [ concat {
"/'<Umacperl"
{menu -m -n "tellMacperl..." -p perlTellProc {
"/O<UOpen This File"
"Save As Droplet"
"Save As Runtime"
"Save As CGI"
"(-"
"Get Output Window"
"Close Output Window"
"Quit"
}
}
{menu -m -n "Quick Save As..." -p perlSaveProc {
"Droplet"
"Runtime"
"CGI"
}
}
{menu -m -n help -p perlHelpProc {
"MacPerl Mode"
"Mac Specifics"
"Perl4 Manual"
"Perl5 Manual"
}}
"(-"
"runTheSelection"
"/R<UrunTheBuffer"
"/R<B<OsaveAndRun"
"runAFile"
"(-"
} [list [list menu -n $perlFilterMenu {}]] {
"selectBufferAsFilter"
"selectFileAsFilter"
"/F<UrepeatLastFilter"
"(-"
} [list [list menu -n $perlOptsMenu {}]] {
} [list [list menu -n $filtOptsMenu {}]] {
} ]
enableMenuItem $perlMenu perlDebugWindow 0
enableMenuItem "tellMacperl..." "Save As CGI" 1
if {$perlPrevScript == {} || $perlPrevScript == {*startup*}} {
enableMenuItem $perlMenu repeatLastFilter 0
}
# General Perl-menu options menu
#
menu -n $perlOptsMenu {
"retrieveOutput"
"autoSwitch"
"promptForArgs"
"useDebugger"
}
markMenuItem $perlOptsMenu useDebugger $perlUseDebug
markMenuItem $perlOptsMenu retrieveOutput $perlGetOutput
markMenuItem $perlOptsMenu autoSwitch $perlAutoSwitch
markMenuItem $perlOptsMenu promptForArgs $perlPromptArgs
# Text Filter options menu
#
menu -n $filtOptsMenu {
"applyToBuffer"
"overwriteSelection"
"(-"
"textFiltersFolder"
"rebuildFilterMenu"
}
markMenuItem $filtOptsMenu overwriteSelection $perlOverwrite
markMenuItem $filtOptsMenu applyToBuffer $perlUsebuffer
#############################################################################
# Build a submenu of "preattached" Perl filters using the names of the
# scripts in the Text Filters directory. Called whenever Text Filters
# folder is reassigned.
#
proc rebuildFilterMenu {{args}} {
global perlFilters perlFilterMenu perlFilterPath
global $perlFilterMenu
eval [buildSubMenu [list $perlFilterPath] $perlFilterMenu textFiltersProc perlFilters]
}
rebuildFilterMenu
#############################################################################
# Use variable tracing to keep global vars and modeVars consistent.
#
trace variable PerlmodeVars(perlUseDebug) w shadowPerl
trace variable PerlmodeVars(perlOverwrite) w shadowPerl
trace variable PerlmodeVars(perlUsebuffer) w shadowPerl
trace variable PerlmodeVars(perlGetOutput) w shadowPerl
trace variable PerlmodeVars(perlAutoSwitch) w shadowPerl
trace variable PerlmodeVars(perlPromptArgs) w shadowPerl
trace variable PerlmodeVars(perlLastFilter) w shadowPerl
trace variable PerlmodeVars(perlCmdlineArgs) w shadowPerl
trace variable PerlmodeVars(perlRecycleOutput) w shadowPerl
trace variable PerlmodeVars(perlVersion) w shadowPerl
# perlFilterPath is now just a regular variable, set from the App Paths submenu
trace variable perlFilterPath w rebuildFilterMenu
# ShadowPerl sets the global vars when the mode vars are modified and
# keeps the menu checkmarked correctly.
#
proc shadowPerl {name1 name2 op} {
global HOME perlMenu perlOptsMenu filtOptsMenu
global perlOverwrite perlUsebuffer perlGetOutput perlAutoSwitch
global perlPromptArgs perlPrevScript perlCmdlineArgs perlUseDebug
global PerlmodeVars
if {$name1 == "PerlmodeVars" && $op == "w"} {
switch $name2 {
"perlUseDebug" {
set perlUseDebug $PerlmodeVars(perlUseDebug)
markMenuItem $perlOptsMenu useDebugger $perlUseDebug
}
"perlOverwrite" {
set perlOverwrite $PerlmodeVars(perlOverwrite)
markMenuItem $filtOptsMenu overwriteSelection $perlOverwrite
}
"perlUsebuffer" {
set perlUsebuffer $PerlmodeVars(perlUsebuffer)
markMenuItem $filtOptsMenu applyToBuffer $perlUsebuffer
}
"perlGetOutput" {
set perlGetOutput $PerlmodeVars(perlGetOutput)
markMenuItem $perlOptsMenu retrieveOutput $perlGetOutput
}
"perlAutoSwitch" {
set perlAutoSwitch $PerlmodeVars(perlAutoSwitch)
markMenuItem $perlOptsMenu autoSwitch $perlAutoSwitch
}
"perlPromptArgs" {
set perlPromptArgs $PerlmodeVars(perlPromptArgs)
markMenuItem $perlOptsMenu promptForArgs $perlPromptArgs
}
"perlCmdlineArgs" {
set perlCmdlineArgs $PerlmodeVars(perlCmdlineArgs)
}
"perlRecycleOutput" {
set perlRecycleOutput $PerlmodeVars(perlRecycleOutput)
}
"perlVersion" {
set perlVersion $PerlmodeVars(perlVersion)
set modeCode ":Tcl:Modes:perl${perlVersion}.tcl"
if {[catch {source $HOME$modeCode}]} {
alertnote "Couldn't load the Perl-mode colorization file \"$modeCode\". Contact the maintainer."
}
}
"perlLastFilter" {
# Don't allow perlPrevScript to be changed from the flags menu
if {$perlPrevScript == "*startup*"} {
set perlPrevScript $PerlmodeVars(perlLastFilter)
enableMenuItem $perlMenu repeatLastFilter 1
} else {
set PerlmodeVars(perlLastFilter) $perlPrevScript
}
}
default {
return
}
}
}
}
#############################################################################
# Menu commands
#############################################################################
############################################################################
# Toggle the perl menu flags
#
proc retrieveOutput {} {
global perlMenu PerlmodeVars perlGetOutput modifiedModeVars
lappend modifiedModeVars [list perlGetOutput PerlmodeVars]
if {$perlGetOutput} then {
set PerlmodeVars(perlGetOutput) 0
} else {
set PerlmodeVars(perlGetOutput) 1
}
}
proc useDebugger {} {
global perlMenu PerlmodeVars perlUseDebug modifiedModeVars
lappend modifiedModeVars [list perlUseDebug PerlmodeVars]
if {$perlUseDebug} then {
set PerlmodeVars(perlUseDebug) 0
} else {
set PerlmodeVars(perlUseDebug) 1
}
}
proc autoSwitch {} {
global perlMenu PerlmodeVars perlAutoSwitch modifiedModeVars
lappend modifiedModeVars [list perlAutoSwitch PerlmodeVars]
if {$perlAutoSwitch} then {
set PerlmodeVars(perlAutoSwitch) 0
} else {
set PerlmodeVars(perlAutoSwitch) 1
}
}
proc overwriteSelection {} {
global perlMenu perlOverwrite PerlmodeVars modifiedModeVars
lappend modifiedModeVars [list perlOverwrite PerlmodeVars]
if {$perlOverwrite} then {
set PerlmodeVars(perlOverwrite) 0
} else {
set PerlmodeVars(perlOverwrite) 1
}
}
proc applyToBuffer {} {
global perlMenu perlUsebuffer PerlmodeVars modifiedModeVars
lappend modifiedModeVars [list perlUsebuffer PerlmodeVars]
if {$perlUsebuffer} then {
set PerlmodeVars(perlUsebuffer) 0
} else {
set PerlmodeVars(perlUsebuffer) 1
}
}
proc promptForArgs {} {
global perlMenu perlPromptArgs PerlmodeVars modifiedModeVars
lappend modifiedModeVars [list perlPromptArgs PerlmodeVars]
if {$perlPromptArgs} then {
set PerlmodeVars(perlPromptArgs) 0
} else {
set PerlmodeVars(perlPromptArgs) 1
}
}
proc textFiltersFolder {} {
global perlMenu perlFilterPath PerlmodeVars modifiedModeVars pathComments
pathProc {} $pathComments(perlFilterPath)
}
#############################################################################
# Switch to MacPerl:
#
proc macperl {} {
launchForeAppl McPL
}
#############################################################################
# Interact with MacPerl in some other way besides executing a script
#
#DTH: note addition of two lines for auto-save
proc perlTellProc {menu name} {
switch -exact $name {
"Open This File" { openInMacperl }
"Save As Droplet" { saveThruMacperl "droplet" }
"Save As Runtime" { saveThruMacperl "runtime" }
"Save As CGI" { saveThruMacperl "cgi" }
"Get Output Window" { openPerlOutput }
"Close Output Window" { sendCloseWinName MacPerl $perlName ;
sendCloseWinName MacPerl "Perl Debug" }
"Quit" { quitMacperl }
}
}
proc perlSaveProc {menu name} {
switch -exact $name {
"Droplet" { saveThruMacperl "auto-droplet" }
"Runtime" { saveThruMacperl "auto-runtime" }
"CGI" { saveThruMacperl "auto-cgi" }
}
}
#############################################################################
# Open the current file under MacPerl. This used to useful for saving files
# as droplets or runtime scripts. Maybe it's still useful for something...?
#
proc openInMacperl {} {
if {[winDirty]} {
case [askyesno -c "Save '[lindex [winNames] 0]'?"] in {
"yes" {save}
"no" {}
"cancel" {return}
}
}
set name [launchForeAppl McPL]
sendOpenEvent -n [file tail $name] [car [winNames -f]]
}
#############################################################################
# Save the script in the current window as a MacPerl droplet or
# runtime script.
#
proc saveThruMacperl {type} {
global ALPHA
set name [file tail [launchBackAppl McPL]]
getWinInfo arr
if {$arr(dirty) == 1} {
case [askyesno -c "Save '[lindex [winNames] 0]' source file also?"] in {
"yes" {save}
"no" {}
"cancel" {return}
}
}
#DTH note the following "if" block which replaced what is in the new "else" block
set myName [lindex [winNames -f] 0]
if {$type == "auto-droplet" || $type == "auto-runtime"} {
if {[file extension $myName] == ".pl"} {
set destfile [AEFilename [file rootname $myName]]
} else {
set destfile [AEFilename [file rootname $myName]]
}
} elseif {$type == "auto-cgi"} {
set destfile [AEFilename "[file rootname $myName].cgi"]
} else {
set destfile [AEFilename [putfile {Save droplet as} [lindex [winNames] 0]]]
}
set script [curlyq [getText 0 [maxPos]]]
#DTH note addition of "auto-xxx" in two lines below
if {$type == "droplet" || $type == "auto-droplet"} {
set saveType "SCPT"
} elseif {$type == "runtime" || $type == "auto-runtime"} {
set saveType "MrP7"
} elseif {$type == "cgi" || $type == "auto-cgi"} {
set saveType "'WWWΩ'"
} elseif {$type == "text"} {
set saveType "TEXT"
}
set err [catch {eval "AEBuild -t 36000 -r \"$name\"" core save {----} [list $script] {dest:} [list $destfile] {fltp:} $saveType } reply ]
if {$err} { message "AEBuild error code $err in saveThruMacperl" }
# The following lines could be used to tell MacPerl to take the script file
# from an existing disk file and then re-save it in the desired form.
#
# set srcfile "\[ [AEFilename [car [winNames -f]]] \]"
# set reply [eval "AEBuild -t 36000 -r \"$name\"" core save {----} [list $srcfile] {dest:} [list $destfile] {fltp:} $saveType ]
#
}
#############################################################################
# Quit a running MacPerl app:
#
proc quitMacperl {} {
foreach proc [processes] {
set sig [lindex $proc 1]
if {$sig == "McPL"} {
sendQuitEvent [lindex $proc 0]
# switchTo is necessary to keep MacPerl from blinking
switchTo [lindex $proc 0]
}
}
}
#############################################################################
# Run the selection as a MacPerl script:
# (No special arrangements are made to provide input or capture the output)
#
proc runTheSelection {} {
global scriptFile scriptStart
set scriptFile [car [winNames -f]]
set scriptStart [lindex [posToRowCol [getPos]] 0]
perlExecuteScript [getSelect]
}
proc runTheBuffer {} {
global scriptFile scriptStart
set scriptFile [car [winNames -f]]
set scriptStart 1
perlExecuteScript [getText 0 [maxPos]]
}
proc runAFile {} {
global scriptFile scriptStart
if {! [catch {getfile "Select a Perl script"} path]} {
set scriptFile $path
set scriptStart 1
perlExecuteFile $path
}
}
proc saveAndRun {} {
global scriptFile scriptStart
save
set path [car [winNames -f]]
set scriptFile $path
set scriptStart 1
perlExecuteFile $path
}
#############################################################################
# Run a preattached Perl text-filter script selected from the menu:
#
proc textFiltersProc {menu name} {
global perlFilters scriptFile scriptStart
perlFileAsFilter $perlFilters($menu:$name)
}
#############################################################################
# Reuse the previous (buffer or file) filter:
#
proc repeatLastFilter {} {
global scriptFile scriptStart perlPrevScript perlMenu PerlmodeVars
if {$perlPrevScript != {}} {
set stype [lindex $perlPrevScript 0]
set name [lindex $perlPrevScript 1]
if {$stype == "file"} {
perlFileAsFilter $name
} elseif {$stype == "buffer"} {
perlBufferAsFilter $name
} else {
message "Bogus filter name : \"$perlPrevScript\""
set perlPrevScript {}
set PerlmodeVars(perlLastFilter) $perlPrevScript
enableMenuItem $perlMenu repeatLastFilter 0
}
}
}
#############################################################################
# Ask for a file containing a Perl script to use as a filter:
#
proc selectFileAsFilter {} {
global scriptFile scriptStart perlPrevScript
if {! [catch {getfile "Select a MacPerl script"} path]} {
perlFileAsFilter $path
}
}
#############################################################################
# Ask for an Alpha buffer containing a Perl script to use as a filter:
#
proc selectBufferAsFilter {} {
global scriptFile scriptStart perlPrevScript
set windows [winNames]
set current [lindex $windows 0]
if {[llength $windows] > 1} {
set name [listpick [lsort $windows]]
if {[string length $name]} {
# get the full name of the chosen window
set wname [lindex [winNames -f] [lsearch -exact $windows $name]]
perlBufferAsFilter $wname
}
}
}
#############################################################################
# Open a file from the MacPerl application folder - used by "Open Special"
#
proc perlOpenFile {menu name} {
set filename [macperlFolder]$name
if {[file exists $filename]} {
edit $filename
} else {
alertnote "That file doesn't exist yet"
}
}
#############################################################################
# Support procs
#############################################################################
#############################################################################
# Prompt the user to enter a string containing command-line args.
#
proc getCmdlineArgs {} {
global PerlmodeVars
set oldargs $PerlmodeVars(perlCmdlineArgs)
if {![catch {prompt "Command-line arguments (if any):" $oldargs} args]} {
set PerlmodeVars(perlCmdlineArgs) $args
} else {
error "getCmdlineArgs: User cancelled"
}
return $args
}
#############################################################################
# Tell MacPerl to run a script file:
#
proc perlExecuteFile {path {args {}} {flags {}}} {
global ALPHA
global perlGetOutput perlAutoSwitch perlPromptArgs perlUseDebug
global scriptFile scriptStart filterHeadLen perlName
if {[string length $path]} {
set perlName [file tail [launchBackAppl McPL]]
if {[string length $perlName]} {
set ok [regexp {(.*):([^:]*)} $path pathname dirname filename]
if {!$ok} { set name $wname }
if {$path != [scriptPath]} {
set filterHeadLen 0
}
if {$perlUseDebug} {
append flags "debug"
}
if {$perlPromptArgs} {
append args " [getCmdlineArgs]"
}
sendCloseWinName $perlName $perlName
sendCloseWinName $perlName "Perl Debug"
if {$perlAutoSwitch || $perlUseDebug} then {
switchTo $perlName
} else {
message "Running file \"$filename\" as Perl script"
watchCursor
}
perlDoScript $perlName $path $args {} $flags
# (not sure which choice is better...)
# if {!$perlAutoSwitch} then {switchTo $ALPHA}
switchTo $ALPHA
#
if {![getMacPerlError]} {
if {$perlGetOutput} then {openPerlOutput}
}
} else {
alertnote "Couldn't run MacPerl"
}
} else {
alertnote "No file specified to execute"
}
}
#############################################################################
# Run a MacPerl script, passed explicitly as a string:
#
# If no "#!/bin/perl" line already exists, one is preprended to the script
# by wrapSelectScript, which also sets $filterHeadLen for use by
# getMacPerlError.
#
proc perlExecuteScript {script {args ""} {flags {}} } {
global perlGetOutput perlAutoSwitch perlPromptArgs perlName
global scriptFile scriptStart filterHeadLen perlUseDebug ALPHA
if {$script != ""} {
set script [wrapSelectScript $script]
if {![regexp {(.*):([^:]*)} $scriptFile pathname dirname filename]} {
set filename $scriptFile
}
set perlName [file tail [launchBackAppl McPL]]
if {[string length $perlName]} {
if {$perlUseDebug} {
append flags "debug"
}
if {$perlPromptArgs} {
append args " [getCmdlineArgs]"
}
sendCloseWinName $perlName $perlName
sendCloseWinName $perlName "Perl Debug"
if {$perlAutoSwitch || $perlUseDebug} then {
switchTo $perlName
} else {
message "Running buffer \"$filename\" as Perl script"
watchCursor
}
perlDoScript $perlName $script $args {} $flags
switchTo $ALPHA
if {![getMacPerlError]} {
if {$perlGetOutput} then {openPerlOutput}
}
}
} else {
alertnote "Can't run an empty script"
}
}
#############################################################################
# Prepare the contents of a disk file for use as a text-filter script.
# (calls perlTextFilter to actually run the script)
#
proc perlFileAsFilter {path} {
global scriptFile scriptStart perlPrevScript perlMenu PerlmodeVars
regexp {(.*):([^:]*)} $path pathname dirname name
if {![catch {readFile $path} coreScript]} {
set scriptFile $path
set scriptStart 1
set script [wrapFilterScript $coreScript]
set perlPrevScript [list "file" $path]
set PerlmodeVars(perlLastFilter) $perlPrevScript
enableMenuItem $perlMenu repeatLastFilter 1
message "Running file \"$name\" as text filter ..."
perlTextFilter $script
} else {
set perlPrevScript {}
set PerlmodeVars(perlLastFilter) $perlPrevScript
enableMenuItem $perlMenu repeatLastFilter 0
alertnote "Couldn't read the script file : $path"
return
}
}
#############################################################################
# Prepare the contents of a text window for use as a text-filter script.
# (calls perlTextFilter to actually run the script)
#
proc perlBufferAsFilter {wname} {
global scriptFile scriptStart perlPrevScript perlMenu PerlmodeVars perlName
set ok [regexp {(.*):([^:]*)} $wname pathname dirname name]
if {!$ok} { set name $wname }
if {[lsearch [winNames -f] $wname] >= 0} {
set coreScript [getText -w $wname 0 [maxPos -w $wname]]
# Does it have any text in it?
if {[string length $coreScript]} {
set scriptFile $wname
set scriptStart 1
set script [wrapFilterScript $coreScript]
set perlPrevScript [list "buffer" $wname]
set PerlmodeVars(perlLastFilter) $perlPrevScript
enableMenuItem $perlMenu repeatLastFilter 1
message "Running buffer \"$name\" as text filter ..."
perlTextFilter $script
}
} else {
set perlPrevScript {}
set PerlmodeVars(perlLastFilter) $perlPrevScript
enableMenuItem $perlMenu repeatLastFilter 0
alertnote "Couldn't find buffer : $name"
}
}
#############################################################################
# Run a Perl script as a command-line text filter, arranging for a text
# buffer to be attached as standard input. The calling routine should already
# have processed the script with wrapFilterScript. This routine actually
# send the script and takes care of writing the input and reading the output
# files.
#
proc perlTextFilter {script {args {}} {flags {}}} {
global perlOverwrite perlUsebuffer perlPromptArgs
global filterHeadLen scriptFile scriptStart perlUseDebug ALPHA
global perlOutputWindow perlRecycleOutput perlName
set perlName [file tail [launchBackAppl McPL]]
if {![string length $perlName]} {
alertnote "Couldn't run MacPerl"
error "Couldn't run MacPerl"
}
writeStdin
if {$perlUseDebug} {
append flags "debug"
}
if {$perlPromptArgs} {
append args " [getCmdlineArgs]"
}
sendCloseWinName $perlName $perlName
sendCloseWinName $perlName "Perl Debug"
if {$perlUseDebug} then {
switchTo $perlName
perlDoScript $perlName [scriptPath] $args [list [stdinPath]] $flags
set err [getMacPerlError]
} else {
watchCursor
set reply [perlDoScriptBatch $perlName [scriptPath] $args [list [stdinPath]]]
set err [getBatchError $reply]
}
switchTo $ALPHA
if {$err == 0} {
if {$perlUseDebug} {
set outp [sendGetText $perlName $perlName]
} else {
# set outp [parseReplyOutp $reply]
set outp [parseReplyResult $reply]
}
pasteFilterResult $outp
}
}
#############################################################################
# Check the MacPerl output window for error messages.
#
proc getMacPerlError {} {
set diag [getPerlDiag 40]
set errf [parseDiagErrf $diag]
set srcs [parseDiagSrcs $diag]
set mesg [parseDiagMesg $diag]
if {[string length $errf]} {
showPerlDiag $diag [string length $diag] $mesg $errf $srcs
gotoPerlError $errf $srcs $mesg
return 1
} else {
return 0
}
}
#############################################################################
# Check the MacPerl batch reply for error messages.
#
proc getBatchError {reply} {
global perlErrorWindow
set fatalError 0
set diag [parseReplyDiag $reply]
set errf [parseDiagErrf $diag ]
set srcs [parseReplySrcs $reply]
set mesg [parseDiagMesg $diag ]
set errn [parseReplyErrn $reply]
if {$errn} {
showPerlDiag $diag $errn $mesg $errf $srcs
gotoPerlError $errf $srcs $mesg
set fatalError 1
} elseif {[string length $diag] > 0} {
showPerlDiag $diag $errn $mesg $errf $srcs
}
return $fatalError
}
#############################################################################
# Display the Perl diagnostic output in its own window.
#
proc showPerlDiag {diag {errn 1} {mesg {}} {errf {}} {srcs {}}} {
global perlErrorWindow
set currWin [lindex [winNames] 0]
if {[lsearch [winNames] $perlErrorWindow] >= 0} {
bringToFront $perlErrorWindow
setWinInfo read-only 0
deleteText 0 [maxPos]
insertText $diag
} else {
new -n $perlErrorWindow
insertText $diag
}
goto 0
catch {shrinkWindow 2}
setWinInfo dirty 0
setWinInfo read-only 1
bringToFront $currWin
}
#############################################################################
# Bring up a window containing the bug-ridden Perl code and highlight the
# line at which the error was found.
#
proc gotoPerlError {errf srcs {mesg {}}} {
global scriptFile scriptStart filterHeadLen
if {$errf == [scriptPath] || $errf == "<AppleEvent>"} {
set errf $scriptFile
# Convert it to the line number in the original file
set srcs [expr $srcs + $scriptStart - $filterHeadLen - 1]
}
# ... and leave an informative error message
#
if {[string length $mesg]} {
set mesg "$mesg at Line $srcs"
} else {
set mesg "MacPerl flagged an error at Line $srcs"
}
# Bring up the script file and highlight the flagged line
#
catch {gotoFileLine $errf $srcs $mesg} fname
}
#############################################################################
# Read the first block of lines (up to a maximum number) from the MacPerl
# output window.
#
proc getPerlDiag {maxlines} {
global perlName
set pat0 {^[ \t]*$}
set lines {}
# read first $maxlines of output to the MacPerl window
# (faster, but assumes error message won't appear at
# the end of a lot of output).
#
set nlines [sendCountLines $perlName MacPerl]
set nlines [expr ($nlines > $maxlines)?$maxlines:$nlines]
if {$nlines > 0} {
set output [sendGetText $perlName $perlName 1 $nlines]
foreach line [split $output "\r"] {
if {[regexp $pat0 $line mtch]} {
break
} else {
append lines "$line\n"
}
}
}
return $lines
}
#############################################################################
# Extract various items out of the MacPerl diagnostic output
#
# Name of the file in which the error was found
#
proc parseDiagErrf {diag} {
if {![regexp {File '([^']+)'; Line} $diag allofit errf]} {
set errf {}
}
return $errf
}
# The line number on which the error was found
#
proc parseDiagSrcs {diag} {
if {![regexp {File '[^']+'; Line ([0-9]+)} $diag allofit srcs]} {
set srcs 0
}
return $srcs
}
# The error message associated with error
#
proc parseDiagMesg {diag} {
set pat1 {^#(.*)$}
set pat2 {File '([^']+)'; Line ([0-9]+)}
set errMessage {}
set errFound 0
foreach line [split $diag "\n"] {
if {[regexp $pat2 $line mtch num]} {
set errFound 1
} elseif {[regexp $pat1 $line mtch err]} {
if {$errFound == 0} {
set errMessage $err
}
}
}
return $errMessage
}
#############################################################################
# Extract various return parameters out of a MacPerl DoScript reply
#
# Result from batch script
#
proc parseReplyResult {reply} {
if {![regexp {'?\-\-\-\-'?:“([^”]*)”} $reply allofit result]} {
set result {}
}
return $result
}
# Standard output of batch script
#
proc parseReplyOutp {reply} {
if {![regexp {OUTP:“([^”]*)”} $reply allofit outp]} {
set outp {}
}
return $outp
}
# Diagnostic output of the batch script
#
proc parseReplyDiag {reply} {
if {[regexp {diag:“([^”]*)”} $reply allofit diag]} {
} else {
set diag {}
}
return $diag
}
# File alias of the script file in which the error was found
#
proc parseReplyErob {reply} {
if {![regexp {erob:alis\(«(.*)»\)} $reply allofit erob]} {
set erob {}
}
return $erob
}
# First line flagged in error
#
proc parseReplySrcs {reply} {
if {![regexp {erng:{srcs:([0-9]+)[^\}]*}} $reply allofit srcs]} {
set srcs 0
}
return $srcs
}
# Last line flagged in error
#
proc parseReplySrce {reply} {
if {![regexp {erng:{[^\}]*srce:([0-9]+)}} $reply allofit srce]} {
set srce 0
}
return $srce
}
# Error number
#
proc parseReplyErrn {reply} {
if {![regexp {errn:([0-9]+)} $reply allofit errn]} {
set errn 0
}
return $errn
}
#############################################################################
# Take a Perl script and add commands to take the file STDIN as standard
# input and STDOUT as standard output. This allows scripts written as
# Unix command-line filters to be used in the (non-MPW) Mac environment as
# text filters.
#
# If there's already a #! line in the script, then the new commands
# are added after that line. If there was no #! line in the first place,
# one is added, in case MacPerl is set up to require it (can't hurt...)
#
# $filterHeadLen counts the number of lines we add to the top of the
# original script, so that we can allow for it in interpreting error
# messages issued by MacPerl.
#
# *** As of MacPerl 4.1.4, this business is pretty much obsolete ***
#
proc wrapFilterScript {coreScript} {
global scriptStart filterHeadLen interpPat
if {[regexp -indices $interpPat $coreScript allofit cmdln]} {
set endPos [lindex $cmdln 1]
set filterHead [string range $coreScript 0 [expr $endPos+1]]
set coreScript [string range $coreScript [expr $endPos+2] end]
set filterHeadLen 0
incr scriptStart [expr [llength [split $filterHead "\n\r"]] -2]
} else {
set filterHead "#!/bin/perl\r\n"
set filterHeadLen 2
}
set script $filterHead
append script $coreScript
# for debugging purposes, save the script on disk
#
writeScript $script
return $script
}
#############################################################################
# Add a #!/bin/perl line to the script if it doesn't contain one already.
# (MacPerl puts up dialog if this line is missing when it expects it,
# hanging the DoScript and leaving us stuck.)
#
proc wrapSelectScript {coreScript} {
global scriptStart filterHeadLen interpPat
if {[regexp -indices $interpPat $coreScript allofit cmdln]} {
set endPos [lindex $cmdln 1]
set filterHead [string range $coreScript 0 [expr $endPos+1]]
set script $coreScript
set filterHeadLen 0
incr scriptStart [expr [llength [split $filterHead "\n\r"]] -2]
} else {
set script "#!/bin/perl\r\n"
append script $coreScript
set filterHeadLen 1
}
# for debugging purposes, save the script on disk
#
writeScript $script
return $script
}
#############################################################################
# Paste result of the filter operation in place of the input text, or in
# a new window (depending on the flag $perlOverwrite
#
proc pasteFilterResult {text} {
global perlOverwrite perlRecycleOutput perlOutputWindow
global perlUsebuffer
if {!$perlOverwrite} {
if {$perlRecycleOutput &&
[lsearch [winNames] $perlOutputWindow] >= 0} {
bringToFront $perlOutputWindow
} else {
new -n $perlOutputWindow
}
}
if {$perlUsebuffer || $perlRecycleOutput} {
set from 0
set to [maxPos]
} else {
set from [getPos]
set to [selEnd]
}
replaceText $from $to $text
if {!$perlOverwrite || $perlUsebuffer} {
catch {shrinkWindow 2}
goto 0
} else {
catch shrinkWindow
goto $from
}
if {!$perlOverwrite} { setWinInfo dirty 0 }
}
#############################################################################
# Extend the current selection to encompass complete lines. If the
# 'applyToBuffer' flag is checked, then the entire buffer is selected.
#
proc completeSelection {} {
global perlUsebuffer filterInput
set filterInput "buffer \"[lindex [winNames] 0]\""
if {$perlUsebuffer} {
set start 0
set end [maxPos]
} else {
set start [lineStart [getPos]]
set end [nextLineStart [expr [selEnd]-1]]
if {$end == $start} { set end [nextLineStart [selEnd]] }
set startLine [lindex [posToRowCol $start] 0]
set endLine [expr [lindex [posToRowCol $end] 0] - 1]
if {$endLine > $startLine+1} {
set filterInput "lines $startLine to $endLine of $filterInput"
} else {
set filterInput "line $startLine of $filterInput"
}
}
return [list $start $end]
}
#############################################################################
# writeStdin: Extend the selection, as appropriate, and write it to the
# STDIN file in the MacPerl directory.
#
# writeScript: Write the SCRIPT file in the MacPerl directory. MacPerl will
# read the script from this file.
#
proc writeStdin {} {
set res [completeSelection]
set tmpfid [open [stdinPath] "w+"]
puts $tmpfid [eval getText $res]
close $tmpfid
}
# This is unnecessary now, but maybe it'll still useful to save the script
# file for debugging.
#
proc writeScript {script} {
set tmpfid [open [scriptPath] "w+"]
puts $tmpfid $script
close $tmpfid
}
#############################################################################
# Read the MacPerl output window and load the contents, if any, into
# a new Alpha window.
#
proc openPerlOutput {} {
global perlRecycleOutput perlOutputWindow perlName
set output [sendGetText $perlName $perlName]
if {[string length $output]} {
if {$perlRecycleOutput &&
[lsearch [winNames] $perlOutputWindow] >= 0} {
bringToFront $perlOutputWindow
replaceText 0 [maxPos] $output
} else {
new -n $perlOutputWindow
insertText $output
}
catch {shrinkWindow 2}
setWinInfo dirty 0
goto 0
}
}
#############################################################################
# translate special DoScript flags into flags string $usrf
#
proc perlScriptFlags {{flags {}}} {
set usrf {}
if {[lsearch -exact $flags "extract"] >= 0} {
append usrf { "EXTR" 'true'}
} elseif {[lsearch -exact $flags "noextract"] >= 0} {
append usrf { "EXTR" 'fals'}
}
if {[lsearch -exact $flags "debug"] >= 0} {
append usrf { "DEBG" 'true'}
} elseif {[lsearch -exact $flags "nodebug"] >= 0} {
append usrf { "DEBG" 'fals'}
}
if {[lsearch -exact $flags "local"] >= 0} {
append usrf { "MODE" 'LOCL'}
} elseif {[lsearch -exact $flags "batch"] >= 0} {
append usrf { "MODE" 'BATC'}
} elseif {[lsearch -exact $flags "remote"] >= 0} {
append usrf { "MODE" 'RCTL'}
}
return $usrf
}
proc perlScriptArgs {{args {}} {fileargs {}}} {
set nargs 0
set argv {}
foreach item [parseWords $args] {
set item [string trim $item]
if {[string length $item]} {
append argv ", [curlyq $item]"
incr nargs
}
}
foreach filename $fileargs {
set item [string trim $filename]
if {[string length $item]} {
append argv ", [curlyq $item]"
incr nargs
}
}
return $argv
}
#############################################################################
# General Apple Event routines
# (most of these have been moved to Modes:appleEvents.tcl)
#
# DoScript for MacPerl 4.1.3
# (runs in "Local" mode under v4.1.4+)
#
proc perlDoScript {appname script {args {}} {fileargs {}} {flags {}} } {
# form list of quoted "command-line" args
#
if {$script != ""} {
set argv "\[[curlyq [string trim $script]]"
# foreach item [split [join $args " "] " "] {
#}
append argv [perlScriptArgs $args $fileargs]
append argv "]"
set usrf [perlScriptFlags $flags]
set reply [eval "AEBuild -t 36000 -r \"$appname\" misc dosc $usrf \"----\" [list $argv] "]
# alertnote $reply
}
}
# DoScript for MacPerl 4.1.4+
#
proc perlDoScriptBatch {appname script {args {}} {fileargs {}}} {
# form list of quoted "command-line" args
#
if {$script != ""} {
set argv "\[[curlyq [string trim $script]]"
append argv [perlScriptArgs $args $fileargs ]
append argv "]"
set reply [eval "AEBuild -t 36000 -r \"$appname\" misc dosc MODE BATC \"----\" [list $argv]"]
# perlDisplayReply $reply
} else {
set reply {}
}
return $reply
}
# For debugging
#
proc perlDisplayReply {reply} {
set currWin [lindex [winNames] 0]
new -n {*** DoScript Reply **}
insertText $reply
goto 0
catch {shrinkWindow 2}
setWinInfo dirty 0
setWinInfo read-only 1
bringToFront $currWin
}
# DoScript to launch interactive debugger (for MacPerl 4.1.4+)
#
proc perlDoScriptDebug {appname script {args {}} {fileargs {}}} {
# form list of quoted "command-line" args
#
if {$script != ""} {
set argv "\[[curlyq [string trim $script]]"
append argv [perlScriptArgs "$args debug" $fileargs ]
append argv "]"
set reply [eval "AEBuild -t 36000 -r \"$appname\" misc dosc MODE RCTL \"----\" [list $argv]"]
new -n {** DoScriptDebug Reply **}
insertText $reply
goto 0
catch {shrinkWindow 2}
setWinInfo dirty 0
setWinInfo read-only 1
} else {
set reply {}
}
return $reply
}
##############################################################################
# Automatic indexing of Perl subs
#
proc PerlMarkFile {} {
set end [maxPos]
set pos 0
set l {}
while {![catch {search -f 1 -r 1 -m 0 -i 0 {^sub} $pos} res]} {
set start [lindex $res 0]
set end [nextLineStart $start]
set text [lindex [getText $start $end] 1]
set pos $end
set inds($text) [lineStart [expr $start - 1]]
}
if {[info exists inds]} {
foreach f [lsort [array names inds]] {
set next [nextLineStart $inds($f)]
setNamedMark $f $inds($f) $next $next
}
}
}
# Open a 'require'd Perl file.
#
proc perlFindRequire {from {to 0}} {
set reqPat {^[ ]*require[ ]*(\"[^\"]+\"|\'[^\']+\'|[^ ]+)}
if {$to == 0} { set to $from }
set beg [lineStart $from]
set end [nextLineStart $to]
set words [parseWords [getText $beg $end]]
if {[string tolower [lindex $words 0]] != "require"} {
error "Not a require statement"
}
set root [string trim [lindex $words 1] {'"}]
return $root
}
proc inlineRequires {} {
global lastMatchingLines
set reqPat {^[ ]*require[ ]*(\"[^\"]+\"|\'[^\']+\'|[^ ]+)}
set pos 0
while {![catch {search -s -f 1 -r 1 -m 0 -i 1 $reqPat $pos} mtch]} {
[lindex [posToRowCol [lindex $mtch 0]] 0]]
set name [string [eval getText $mtch]
set pos [lindex $mtch 1]
incr matches
}
}
# Open a Perl source file.
#
proc openPerlFile {file {extensions {""}}} {
global perlSearchPath
# Determine absolute file specification
# Ignore $extensions if $file already has an extension
if {[string length [file extension $file]] == 0} {
set extensions {""}
}
foreach ext $extensions {
set filename [absolutePath $file$ext]
if {![catch {openFileQuietly $filename}]} {
message $filename
return
}
}
if {[llength $perlSearchPath] == 0} { buildPerlSearchPath }
foreach folder $perlSearchPath {
foreach ext $extensions {
set filename "$folder$file$ext"
if {![catch {openFileQuietly $filename}]} {
message $filename
return
}
}
}
beep
message "can't find Perl source file \"$file\""
}
# Return a list of folders in which to search for Perl library files,
# including the lib folder in the Perl application directory and the
# $perlLib folder (if it exists) .
# The current folder is not included in the list.
#
# (The $perlLib folder is assigned from the AppPaths submenu.)
#
proc buildPerlSearchPath {} {
global perlLib perlSearchPath
message "building Perl search path..."
set folders {}
# The local lib folder:
if {[info exists perlLib] && [string length $perlLib] > 0} {
set folders [concat $folders [list $perlLib]]
# Search subfolders one level deep:
set folders [concat $folders [listSubfolders $perlLib 1]]
}
# Any "*lib*" folders in the MacPerl application folder:
set macperlPath [nameFromAppl McPL]
set appDir [file dirname $macperlPath]
set folders [concat $folders [list $appDir]]
# Bug: 'glob' is case sensitive!
foreach folder [glob "$appDir:*\[Ll\]ib*"] {
set folders [concat $folders [list $folder]]
# Search subfolders one level deep:
set folders [concat $folders [listSubfolders $folder 1]]
}
# Make sure each folder ends with a colon
set perlSearchPath {}
foreach folder $folders {
set folder "[string trimright $folder {:}]:"
set perlSearchPath [concat $perlSearchPath [list $folder]]
}
}
###########################################################################
#
proc perlHelpProc {menu item} {
global HOME perlDocs
switch $item {
"MacPerl Mode" {
if {[catch {openFileQuietly "$HOME:Help:MacPerl Help"}]} {
alertnote "File not found:\r$HOME:Help:MacPerl Help"
}
}
"Mac Specifics" {
if {[catch {openFileQuietly "$HOME:Help:MacPerl.Specifics"}]} {
alertnote "File not found:\r$HOME:Help:MacPerl.Specifics"
}
}
"Perl4 Manual" {
if {[catch {openFileQuietly "$HOME:Help:Perl Commands"}]} {
alertnote "File not found:\r$HOME:Help:Perl Commands"
}
}
"Perl5 Manual" {
catch {editMark "$HOME:Help:Perl Commands" Perl5 -r}
}
}
}
proc electricPerlLeft {} {
set prevChar [lookAt [expr [getPos] - 1]]
if {$prevChar == " " || $prevChar == "\)"} {
electricLeft
return
}
deleteText [getPos] [selEnd]
insertText "\{"
}
proc electricPerlRight {} {
set prevChar [lookAt [expr [getPos] - 1]]
if {$prevChar == " " || $prevChar == ";" || $prevChar == "\t" || $prevChar == "\}"} {
electricRight
return
}
deleteText [getPos] [selEnd]
insertText "\}"
catch {blink [matchIt "\}" [expr [getPos]-2]]}
return
}
bind '\r' tclCarriageReturn Perl
bind '\}' <s> electricPerlRight Perl
bind '\{' <s> electricPerlLeft Perl
bind '\;' electricSemi Perl
bind '\t' <z> doATab Perl
#